﻿
// 2023/2/28: 首个版本
// 2023/3/29: 新增bgrToYuv420。splitYuv420ToSameSize支持3倍/6倍
// 2023/4/4: 确保内存读写安全
// 2023/7/6: 新增nv12ToYuv420
// 2023/7/6: 新增resizeYuv420Quarter。Third/Sixth更名为OneThird/Sixth
// 2023/8/24: 新增yuv420ToNv12
// 2023/10/26: 优化raw8/12/14/16转yuv420
// 2023/12/1: 新增raw8ToBgr, yuv420ToBgr
// 2024/6/12: 支持spadas9

#ifndef YUV_CONVERSION_CPU_H_
#define YUV_CONVERSION_CPU_H_

#include "spadas.h"
#include "NextCompatibleImage.h"

namespace videonext
{
	using namespace spadas;

	void calcSplitYuv420Size(Size2D rawSize, UInt forWidth, Size2D& ySize, Size2D& uSize, Size2D& vSize);
	void calcSplitNv12Size(Size2D rawSize, UInt forWidth, Size2D& ySize, Size2D& uSize, Size2D& vSize);
	void calcSplitYuv411Size(Size2D rawSize, UInt forWidth, Size2D& ySize, Size2D& uSize, Size2D& vSize);

	// input: ImagePointerColor or IplImageColor, output: renew AVFrameYUV420P
	Bool bgrToYuv420(CompatibleImage input, CompatibleImage& output);

	// input: ImagePointerColor or IplImageColor, output: renew 
	Bool bgrToYuv411(CompatibleImage input, Binary& output);

	// input: ImagePointerColor or IplImageColor, output: renew 
	Bool bgrToYuv4p(CompatibleImage input, Binary& output);

	// input: AVFrameNV12, output: renew AVFrameYUV420P
	Bool nv12ToYuv420(CompatibleImage input, CompatibleImage& output);

	// input: AVFrameYUV420P, output: renew AVFrameNV12
	Bool yuv420ToNv12(CompatibleImage input, CompatibleImage& output);

	// input: AVFrameYUV420P, output: renew ImagePointerGray or new CompatibleChannelGray
	Bool splitYuv420(CompatibleImage input, UInt forWidth, CompatibleImage& y, CompatibleImage& u, CompatibleImage& v);

	// input: AVFrameYUV420P, output: renew ImagePointerGray or new CompatibleChannelGray
	Bool splitYuv420ToSameSize(CompatibleImage input, UInt resizeRatio/* 1, 2, 3, 4, 6 */, CompatibleImage& y, CompatibleImage& u, CompatibleImage& v);

	// input: AVFrameYUV420P, output: renew ImagePointerGray or new CompatibleChannelGray
	Bool splitYuv420ToSameSizeSegment(CompatibleImage input, UInt resizeRatio/* 1, 2, 4 */, Region2D segment, CompatibleImage& y, CompatibleImage& u, CompatibleImage& v);

	// input: AVFrameNV12, output: renew ImagePointerGray or new CompatibleChannelGray
	Bool splitNv12(CompatibleImage input, UInt forWidth, CompatibleImage& y, CompatibleImage& u, CompatibleImage& v);

	// output: renew ImagePointerGray
	Bool splitYuv411(Binary input, Size2D inputSize, UInt forWidth, CompatibleImage& y, CompatibleImage& u, CompatibleImage& v);

	// output: renew ImagePointerGray
	Bool splitYuv411ToSameSize(Binary input, Size2D inputSize, UInt resizeRatio/* 1, 2, 4 */, CompatibleImage& y, CompatibleImage& u, CompatibleImage& v);

	// input: ImagePointerGray or IplImageGray or CompatibleChannelGray with the same size, output: renew ImagePointerColor
	Bool yuvToBgrFine(CompatibleImage y, CompatibleImage u, CompatibleImage v, CompatibleImage& output);

	// input: ImagePointerGray or IplImageGray or CompatibleChannelGray with the same size, output: renew ImagePointerColor
	Bool yuvToBgrCoarse(CompatibleImage y, CompatibleImage u, CompatibleImage v, CompatibleImage& output);

	// input: AVFrameYUV420P, output: renew AVFrameYUV420P
	Bool resizeYuv420Half(CompatibleImage src, CompatibleImage& dst);

	// input: AVFrameYUV420P, output: renew AVFrameYUV420P
	Bool resizeYuv420OneThird(CompatibleImage src, CompatibleImage& dst);

	// input: AVFrameYUV420P, output: renew AVFrameYUV420P
	Bool resizeYuv420Quarter(CompatibleImage src, CompatibleImage& dst);

	// input: AVFrameYUV420P, output: renew AVFrameYUV420P
	Bool resizeYuv420OneSixth(CompatibleImage src, CompatibleImage& dst);

	// input: AVFrameYUV420P, output: renew AVFrameYUV420P
	Bool resizeYuv420OneEighth(CompatibleImage src, CompatibleImage& dst, Bool clipToDividable = FALSE);

	// input: AVFrameYUV420P, output: renew ImagePointerGray
	Bool resizeOnlyYHalf(CompatibleImage src, CompatibleImage& dst);

	// output: renew AVFrameYUV420P
	Bool yuv411ToYuv420(Binary input, Size2D inputSize, CompatibleImage& dst);

	// output: renew AVFrameYUV420P
	Bool yuv4pToYuv420(Binary input, Size2D inputSize, CompatibleImage& dst);

	// input: AVFrameYUV420P, output: renew 
	Bool yuv420ToYuv4p(CompatibleImage input, Binary& output);

	// output: renew AVFrameYUV420P
	Bool yuv422ToYuv420(Binary input, Size2D inputSize, CompatibleImage& dst);

	// output: renew AVFrameYUV420P
	Bool raw8ToYuv420(Binary input, Size2D inputSize, CompatibleImage& dst);

	// output: renew AVFrameYUV420P
	Bool raw12ToYuv420(Binary input, Size2D inputSize, CompatibleImage& dst);

	// output: renew AVFrameYUV420P
	Bool raw14ToYuv420(Binary input, Size2D inputSize, CompatibleImage& dst);

	// output: renew AVFrameYUV420P
	Bool raw16ToYuv420(Binary input, Size2D inputSize, CompatibleImage& dst);

	// output: renew AVFrameYUV420P
	Bool y16ToYuv420(Binary input, Size2D inputSize, CompatibleImage& dst);

	// output: renew ImagePointerColor
	Bool raw8ToBgr(Binary input, Size2D inputSize, CompatibleImage& dst);

	// input: AVFrameYUV420P, output: renew ImagePointerColor
	Bool yuv420ToBgr(CompatibleImage input, CompatibleImage& dst);
}

#endif
